package com.ruifu.doc.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.fhzncloud.cloud.common.core.util.PageR;
import com.fhzncloud.cloud.common.security.service.CloudUser;
import com.fhzncloud.cloud.common.security.util.SecurityUtils;
import com.ruifu.common.config.ActConstants;
import com.ruifu.common.feign.RemoteActService;
import com.ruifu.common.feign.RemoteWorkSheetService;
import com.ruifu.common.po.DmDocVer;
import com.ruifu.common.vo.PageResultVO;
import com.ruifu.common.vo.ResultVO;
import com.ruifu.common.vo.actanddoc.ActivitiVO;
import com.ruifu.common.vo.actanddoc.Flag;
import com.ruifu.common.vo.actanddoc.ProcessParams;
import com.ruifu.common.vo.worksheet.WsCommonSheet;
import com.ruifu.doc.conf.DocFinal;
import com.ruifu.doc.dto.docver.*;
import com.ruifu.doc.mapper.DmDocVerMapper;
import com.ruifu.doc.service.DmDocVerService;
import com.ruifu.doc.vo.docmaster.QueryMyAudiVO;
import com.ruifu.doc.vo.docver.DmDocVerVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 文档版本控制层
 *
 * @author nyr
 * @create 2019/8/26
 */
@RestController
@CrossOrigin
@Slf4j
@Transactional(rollbackFor = Exception.class)
@RequestMapping("/dmDocVer")
public class DmDocVerController {
    @Autowired
    private DmDocVerService dmDocVerService;

    @Autowired(required = false)
    private DmDocVerMapper dmDocVerMapper;

    @Autowired
    private RemoteActService remoteActService;

    @Autowired(required = false)
    private RemoteWorkSheetService remoteWorkSheetService;
    /**
     * 文件Bean
     */
    private CloudUser cloudUser;

    /**
     * 通过url请求方法之前,调用该方法获取登陆人信息
     */
    @ModelAttribute
    public void before() {
        cloudUser = SecurityUtils.getUser();
    }

    /**
     * 联合查询
     *
     * @param pageNum
     * @param pageSize
     * @param dmDocVerQueryDTO
     * @return
     */
    @PostMapping(value = "/findByQuery/{pageNum}/{pageSize}")
    public PageResultVO findByQuery(@PathVariable("pageNum") int pageNum, @PathVariable("pageSize") int pageSize,
                                    @RequestBody DmDocVerQueryDTO dmDocVerQueryDTO) {
        pageNum = pageNum <= 0 ? 1 : pageNum;
        pageSize = pageSize < 5 ? 5 : pageSize;
        return dmDocVerService.findByQuery(pageNum, pageSize, dmDocVerQueryDTO, cloudUser);
    }

    /**
     * 所有(不分页导出Excel清单)
     *
     * @return
     */
    @PostMapping(value = "/exportExcel")
    public List<DmDocVerVO> exportExcel(@RequestBody DmDocVerQueryDTO dmDocVerQueryDTO) {
        return dmDocVerService.findAll(dmDocVerQueryDTO, cloudUser);
    }


    /**
     * 文档详情
     *
     * @param dvDvId
     * @return
     */
    @GetMapping(value = "/findById/{dvDvId}")
    public DmDocVerVO findById(@PathVariable("dvDvId") Long dvDvId) {
        return dmDocVerService.findById(dvDvId,cloudUser);
    }


    /**
     * 新建
     *
     * @param dmDocVerInsertDTO
     * @return
     */
    @PostMapping(value = "/insert")
    public ResultVO insert(@RequestBody DmDocVerInsertDTO dmDocVerInsertDTO) {
        try {
            dmDocVerService.insert(dmDocVerInsertDTO, cloudUser);
            return new ResultVO(true, "新建成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "新建失败");
        }
    }

    /**
     * 删除
     *
     * @param dvDvId 版本id
     * @return
     */
    @GetMapping(value = "/deleteByDvDvId/{dvDvId}")
    public ResultVO deleteByDvDvId(@PathVariable("dvDvId") Long dvDvId) {
        try {
            dmDocVerService.deleteByDvDvId(dvDvId, cloudUser);
            return new ResultVO(true, "删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "删除失败");
        }
    }

    /**
     * 批量删除
     *
     * @param dvDvIdList
     * @return
     */
    @PostMapping(value = "/delete")
    public ResultVO delete(@RequestBody List<Long> dvDvIdList) {
        try {
            dmDocVerService.delete(dvDvIdList, cloudUser);
            return new ResultVO(true, "删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "删除失败");
        }
    }

    /**
     * 修改
     *
     * @param dmDocVerUpdateDTO
     * @return
     */
    @PostMapping(value = "/update")
    public ResultVO update(@RequestBody DmDocVerUpdateDTO dmDocVerUpdateDTO) {
        try {
            dmDocVerService.update(dmDocVerUpdateDTO, cloudUser);
            return new ResultVO(true, "修改成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "修改失败");
        }

    }

    /**
     * 转交所有权
     *
     * @param dvDvId
     * @param dvOwner
     * @return
     */
    @GetMapping(value = "/updateOwnership/{dvDvId}/{dvOwner}")
    public ResultVO updateOwnership(@PathVariable("dvDvId") Long dvDvId, @PathVariable("dvOwner") Integer dvOwner) {
        try {
            dmDocVerService.updateOwnership(dvDvId, dvOwner, cloudUser);
            return new ResultVO(true, "转交成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "转交失败");
        }
    }

    /**
     * 另存为
     *
     * @param dvDvId
     * @param dmDocName
     * @param dmDocCode
     * @return
     */
    @GetMapping(value = "/insertSaveAs/{dvDvId}/{dmDocName}/{dmDocCode}")
    public ResultVO insertSaveAs(@PathVariable("dvDvId") Long dvDvId,
                                 @PathVariable("dmDocName") String dmDocName,
                                 @PathVariable("dmDocCode") String dmDocCode) {
        try {
            dmDocVerService.insertSaveAs(dvDvId, dmDocName, dmDocCode, cloudUser);
            return new ResultVO(true, "成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "失败");
        }

    }

    /**
     * 版本升级
     *
     * @param dvDvId
     * @return
     */
    @GetMapping(value = "/newVersion")
    public ResultVO newVersion(Long dvDvId) {
        try {
            dmDocVerService.newVersion(dvDvId, cloudUser);
            return new ResultVO(true, "升版成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, e.getMessage());
        }
    }

    /**
     * 批量录入
     *
     * @param files   文件数组
     * @param request
     * @return
     */
    @PostMapping(value = "/plInsert")
    public ResultVO plInsert(@RequestParam MultipartFile[] files, HttpServletRequest request) {
        try {
            //从请求中获取批量录入传输对象的JSON数组
            String[] dmDocVerPLInsertDTOJSONs = request.getParameterValues("dmDocVerPLInsertDTOJSONs");

            //判断接收到的数据是否完整
            if (files.length != dmDocVerPLInsertDTOJSONs.length) {
                throw new RuntimeException("批量录入数据不完整,无法完成操作");
            }

            //创建一个集合,用于发送到服务层
            List<DmDocVerPLInsertDTO> dmDocVerPLInsertDTOList = new ArrayList<>();

            //遍历文件数组
            for (int i = 0; i < files.length; i++) {
                //将JSON转换为文档版本DTO对象
                DmDocVerPLInsertDTO dmDocVerPLInsertDTO = JSON.parseObject(dmDocVerPLInsertDTOJSONs[i], DmDocVerPLInsertDTO.class);

                //将文件设置到DTO对象中
                dmDocVerPLInsertDTO.setFile(files[i]);

                //设置到集合中
                dmDocVerPLInsertDTOList.add(dmDocVerPLInsertDTO);
            }
            dmDocVerService.plInsert(dmDocVerPLInsertDTOList, cloudUser);
            return new ResultVO(true, "批量录入成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, e.getMessage());
        }
    }

    /**
     * (提交)启动流程实例
     *
     * @param processDefinitionDto
     */
    @PostMapping(value = "/submitDocument")
    public ResultVO submitDocument(@RequestBody ProcessParams processDefinitionDto) {
        try {
            processDefinitionDto.setDvDvId(processDefinitionDto.getDvDvId()+ ActConstants.DOC_SUFFIX);
            Flag flag = remoteActService.submitDocument(processDefinitionDto);
            //是否启动成功
            if (flag != null) {
                if (flag.getIsSubmitSucceed()) {
                    log.info("文档id["+processDefinitionDto.getDvDvId()+"]提交成功,流程已启动");
                    //截取id
                    String actVoPrefix = processDefinitionDto.getDvDvId().substring(0,processDefinitionDto.getDvDvId().indexOf("-"));
                    //获取对应的文档版本
                    DmDocVer dmDocVer = dmDocVerMapper.findById(Long.valueOf(actVoPrefix));
                    dmDocVer.setDvIsFlow(true);
                    dmDocVer.setDvCtrStatus(DocFinal.PROCESS);
                    //修改文档为在流程中
                    dmDocVerMapper.update(dmDocVer, cloudUser);
                }
            }
            return new ResultVO(true, "提交成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResultVO(false, "提交失败");
        }
    }


    /**
     * 待办/已办
     *
     * @param processDefinitionDto
     * @return
     */
    @PostMapping(value = "/queryMyAudit/{page}/{size}")
    public PageR<List<QueryMyAudiVO>> audit(@RequestBody ProcessDefinitionDto processDefinitionDto,
                                      @PathVariable("page") Integer page,@PathVariable("size") Integer size) {
        //初始化返回值集合
        List<QueryMyAudiVO> queryMyAudiVoList = new ArrayList<>();
        //初始化流程信息集合
        PageR<List<ActivitiVO>> actVoList;
        //true 已处理  false待处理
        Boolean isAudit = processDefinitionDto.getIsAudit();
        if (isAudit){
            //查询已处理的流程信息
            actVoList = remoteActService.queryDoneTasks(page, size);

        }else {
            //查询待处理的流程信息
            actVoList = remoteActService.iReview(page, size);
        }
        if (CollectionUtils.isNotEmpty(actVoList.getData())) {
            //遍历流程信息
            for (ActivitiVO activitiVO : actVoList.getData()) {
                //待办VO对象
                QueryMyAudiVO queryMyAudiVO = new QueryMyAudiVO();
                //前缀id
                String actVoPrefix = activitiVO.getBusinessKey().substring(0,activitiVO.getBusinessKey().indexOf("-"));
                //后缀type
                String actVoSuffix = activitiVO.getBusinessKey().substring(activitiVO.getBusinessKey().lastIndexOf("-") + 1);
                switch (actVoSuffix){
                    case ActConstants.DOC:
                        //查询已经审核过的对象信息包括已经删除的对象
                        getDocVo(queryMyAudiVoList, activitiVO, queryMyAudiVO,actVoPrefix);
                        break;
                        //作废通知
                    case ActConstants.VOID_NOTICE:
                        getWorkSingleVo(queryMyAudiVoList, activitiVO, queryMyAudiVO, ActConstants.VOID_NOTICE);
                        break;
                        //变更通知
                    case ActConstants.CHANGE_NOTIFICATION:
                        getWorkSingleVo(queryMyAudiVoList, activitiVO, queryMyAudiVO, ActConstants.CHANGE_NOTIFICATION);
                        break;
                        //问题报告
                    case ActConstants.PROBLEM_REPORT:
                        getWorkSingleVo(queryMyAudiVoList, activitiVO, queryMyAudiVO, ActConstants.PROBLEM_REPORT);
                        break;
                        //变更申请
                    case ActConstants.CHANGE_REQUEST:
                        getWorkSingleVo(queryMyAudiVoList, activitiVO, queryMyAudiVO, ActConstants.CHANGE_REQUEST);
                        break;
                        //零部件
                    case ActConstants.MATERIEL:
                        break;
                    default:break;
                }
            }
        }
        return PageR.ok(queryMyAudiVoList,actVoList.getTotal());
    }

    /**
     * 待办-已办 文档VO
     * @param queryMyAudiVoList
     * @param activitiVO
     * @param queryMyAudiVO
     * @param actVoPrefix
     */
    private void getDocVo(List<QueryMyAudiVO> queryMyAudiVoList, ActivitiVO activitiVO, QueryMyAudiVO queryMyAudiVO,String actVoPrefix) {
        DmDocVer dmDocVer = dmDocVerMapper.findByIdAndDelete(Long.valueOf(actVoPrefix));
        if (dmDocVer != null) {
            getActInfo(activitiVO, queryMyAudiVO);
            getDocInfo(queryMyAudiVO, dmDocVer);
        }
        queryMyAudiVoList.add(queryMyAudiVO);
    }

    /**
     * 待办-已办 工作单VO
     * @param queryMyAudiVoList
     * @param activitiVO
     * @param queryMyAudiVO
     * @param actVoPrefix
     */
    private void getWorkSingleVo(List<QueryMyAudiVO> queryMyAudiVoList, ActivitiVO activitiVO,
                               QueryMyAudiVO queryMyAudiVO, String actVoPrefix) {
        //获取变更单id
        String idString = activitiVO.getBusinessKey().substring(0,activitiVO.getBusinessKey().indexOf("-"));
        BigInteger id=new BigInteger(idString);
        //根据id+类别获取变更单对象
        WsCommonSheet wsCommonSheet = remoteWorkSheetService.feignFindWsById(id,actVoPrefix);
        if (wsCommonSheet != null) {
            getActInfo(activitiVO, queryMyAudiVO);
            getWsInfo(queryMyAudiVO, wsCommonSheet);
        }
        queryMyAudiVoList.add(queryMyAudiVO);
    }

    /**
     * 工作单信息VO
     * @param queryMyAudiVO
     * @param wsCommonSheet
     * @return
     */
    private QueryMyAudiVO getWsInfo(QueryMyAudiVO queryMyAudiVO, WsCommonSheet wsCommonSheet) {
        //设置id

        queryMyAudiVO.setDvDvId(wsCommonSheet.getCmId().longValue());

        //类别
        queryMyAudiVO.setCategory(wsCommonSheet.getCmFeginClassFlag());

        //编号
        queryMyAudiVO.setDmDocCode(wsCommonSheet.getCmCode());

        //名称
        queryMyAudiVO.setDmDocName(wsCommonSheet.getCmName());

        //类型名称
        queryMyAudiVO.setDcDoccName(wsCommonSheet.getCmTypeName());

        //责任人
        queryMyAudiVO.setDvOwner(wsCommonSheet.getCreator());

        //文件名
        if (wsCommonSheet.getCmAccessoriesName()!=null){
            queryMyAudiVO.setFiFileName(wsCommonSheet.getCmAccessoriesName());
        }
        //文件id
        if (wsCommonSheet.getCmAccessoriesName()!=null){
            queryMyAudiVO.setFileId(wsCommonSheet.getCmAccessoriesId().longValue());
        }

        return queryMyAudiVO;
    }

    /**
     * 文档信息VO
     * @param queryMyAudiVO
     * @param dmDocVer
     * @return
     */
    private QueryMyAudiVO getDocInfo(QueryMyAudiVO queryMyAudiVO, DmDocVer dmDocVer) {
        //设置文档id
        queryMyAudiVO.setDvDvId(dmDocVer.getDvDvId());

        //文档类别
        queryMyAudiVO.setCategory(ActConstants.DOC);

        //文档编号
        queryMyAudiVO.setDmDocCode(dmDocVer.getDmDocMaster().getDmDocCode());

        //文档名称
        queryMyAudiVO.setDmDocName(dmDocVer.getDmDocMaster().getDmDocName());

        //文档类型名称
        queryMyAudiVO.setDcDoccName(dmDocVer.getDmDocMaster().getDmDocc().getDcDoccName());

        //责任人
        queryMyAudiVO.setDvOwner(dmDocVer.getDvOwner());

        //文件名
        if (dmDocVer.getDmFile().getFiFileName()!=null){
            queryMyAudiVO.setFiFileName(dmDocVer.getDmFile().getFiFileName());
        }

        //文件id
        if (dmDocVer.getDvFileId()!=null){
            queryMyAudiVO.setFileId(dmDocVer.getDvFileId());
        }
        return queryMyAudiVO;
    }

    /**
     * 流程信息VO
     * @param activitiVO
     * @param queryMyAudiVO
     * @return
     */
    private QueryMyAudiVO getActInfo(ActivitiVO activitiVO, QueryMyAudiVO queryMyAudiVO) {
        //设置任务id
        queryMyAudiVO.setTaskId(activitiVO.getTaskId());
        //设置当前环节名称
        queryMyAudiVO.setPresentLinkName(activitiVO.getPresentLinkName());
        //设置实例id
        queryMyAudiVO.setProcessInstanceId(activitiVO.getProcessInstanceId());
        //设置上一环节名称
        queryMyAudiVO.setUpLinkName(activitiVO.getUpLinkName());
        //设置上一环节办理人
        queryMyAudiVO.setUpTaskAss(activitiVO.getUpTaskAss());
        //N标识编辑节点(作用于是否重新提交)
        queryMyAudiVO.setFlowMassage(activitiVO.getFlowMassage());
        //提交时间
        queryMyAudiVO.setLastUpdateTime(activitiVO.getLastUpdateTime());
        return queryMyAudiVO;
    }

    /**
     * 校验/审核/编辑...
     *
     * @param processDefinitionDto
     * @return
     */
    @PostMapping(value = "/pass")
    public ResultVO pass(@RequestBody ProcessParams processDefinitionDto) {
        try {
            Flag flag = remoteActService.flag(processDefinitionDto);
            //是否处理成功
            if (flag.getIsSubmitSucceed()){
                //流程是否结束
                if (DocFinal.DOC_IS_FINISH.equals(flag.getIsFinish())){
                    switch (processDefinitionDto.getCategory()){
                        //文档
                        case ActConstants.DOC:
                            log.info("文档id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            DmDocVer dmDocVer = dmDocVerMapper.findById(Long.valueOf(processDefinitionDto.getDvDvId()));
                            //修改文档状态为已发布
                            dmDocVer.setDvCtrStatus(DocFinal.PUBLISHED);
                            //修改流程状态
                            dmDocVer.setDvIsFlow(false);
                            //生效时间
                            dmDocVer.setDvApprovedDate(new Date());
                            dmDocVerMapper.update(dmDocVer, cloudUser);
                            break;
                        //作废通知
                        case ActConstants.VOID_NOTICE:
                            //主键  后缀  流程是否结束
                            log.info("作废通知单id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            BigInteger vnsId=new BigInteger(processDefinitionDto.getDvDvId());
                            remoteWorkSheetService.feignReviewCommit(vnsId,ActConstants.VOID_NOTICE,true);
                            break;
                        //问题报告
                        case ActConstants.PROBLEM_REPORT:
                            log.info("问题报告单id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            BigInteger pesId=new BigInteger(processDefinitionDto.getDvDvId());
                            remoteWorkSheetService.feignReviewCommit(pesId,ActConstants.PROBLEM_REPORT,true);
                            break;
                        //变更申请
                        case ActConstants.CHANGE_REQUEST:
                            log.info("变更申请单id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            BigInteger crsId=new BigInteger(processDefinitionDto.getDvDvId());
                            remoteWorkSheetService.feignReviewCommit(crsId,ActConstants.CHANGE_REQUEST,true);
                            break;
                        //变更通知
                        case ActConstants.CHANGE_NOTIFICATION:
                            log.info("变更通知单id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            BigInteger cnsId=new BigInteger(processDefinitionDto.getDvDvId());
                            remoteWorkSheetService.feignReviewCommit(cnsId,ActConstants.CHANGE_NOTIFICATION,true);
                            break;
                        //零部件
                        case ActConstants.MATERIEL:
                            log.info("零部件id["+processDefinitionDto.getDvDvId()+"]流程已结束");
                            break;
                        default:break;
                    }
                }
                log.info("处理成功");
                return new ResultVO(true, "处理成功");
            }else {
                log.info("当前流程步骤已被其他人处理");
                return new ResultVO(true, "当前流程步骤已被其他人处理");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("处理失败");
            return new ResultVO(false, "处理失败");
        }

    }

    /**
     * 根据用户id和文档版本id查询权限
     *
     * @param DvDvId 文档版本id
     * @return
     */
    @GetMapping(value = "/findPermission/{DvDvId}")
    public String findPermissionByUserIdAndPtId(@PathVariable("DvDvId") Long DvDvId) {
        return dmDocVerService.findPermissionByUserIdAndPtId(cloudUser, DvDvId);
    }

    /**
     * 根据用户id和文档版本数组查询权限
     *
     * @param dvDvIdArr 文档版本id数组
     * @return
     */
    @PostMapping(value = "/findPermissionList")
    public List<String> findPermissionByUserIdAndPtId(@RequestBody Long[] dvDvIdArr) {
        return dmDocVerService.findPermissDocList(cloudUser, dvDvIdArr);
    }

}
